/// <reference path="../../typings/index.d.ts" />
// import * as React from "React";

namespace View {

    var state: any;

    export class Comment extends React.Component<{ author: string }, {}> {
        render() {
            return (
                <div className="comment">
                    <h2 className="commentAuthor">
                        {this.props.author}
                    </h2>
                    {this.props.children}
                </div>
            );
        }
    }

    export class CommentList extends React.Component<{ data: { id: number; author: string, text: string }[] }, {}> {
        render() {
            let commentNodes = this.props.data.map((node) => {
                return (
                    <Comment author={node.author} key={node.id}>
                        {node.text}
                    </Comment>
                )
            });
            return (
                <div className='commentList'>
                    {commentNodes}
                </div>
            );
        }
    }

    export class CommentForm extends React.Component<{ onCommentSubmit?: (author: string, text: string) => void }, { author?: string, text?: string }> {
        constructor() {
            super();
            this.state = this.getInitialState();
        }
        getInitialState() {
            return { author: "z", text: "ha" };
        }
        handleAuthorChange = (e: React.FormEvent) => {
            console.log('author changed', (e.target as any).value);
            this.setState({ author: '' + (e.target as any).value })
        }
        handleTextChange = (e: React.FormEvent) => {
            console.log('text changed', this);
            this.setState({ text: (e.target as any).value })
        }
        handleSubmit = (e: React.FormEvent) => {
            e.preventDefault();
            let author = this.state.author;
            let text = this.state.text;
            console.log(author, text);
            if (!author || !text) {
                return;
            }
            this.setState({ author: '', text: '' })
            this.props.onCommentSubmit(author, text);
        }
        render() {
            return (
                <form className='commentForm' onSubmit={this.handleSubmit}>
                    <input type='text' placeholder='Your name'
                        value={this.state.author}
                        onChange={this.handleAuthorChange}
                    />
                    <input type='text' placeholder='Say something...'
                        value={this.state.text}
                        onChange={this.handleTextChange}
                    />
                    <input type='submit' value='Post' />
                </form>
            )
        }
    }


    export class CommentBox extends React.Component<{ data: { id: number; author: string, text: string }[], url?: string, pollInterval?: number }, { data: { id: number; author: string, text: string }[] }> {

        getInitialState() {
            console.log(`CommentBox getInitialState is called...state:${JSON.stringify(this.state)}`);
        }
        componentWillMount() {
            console.log(`componentWillMount is called. state:${JSON.stringify(this.state)}`);
        }

        loadDataFromServer() {
            if (this.props.url) {
                $.ajax({
                    url: this.props.url,
                    dataType: 'json',
                    cache: false,
                    success: ((data: any) => {
                        console.log('from ajax:', data);
                        this.setState({ data: data })
                    }).bind(this),
                    error: ((data: any) => {
                        console.log(`Error: ${data}`);
                    }).bind(this)
                });
            }
        }

        componentDidMount() {
            console.log(`componentDidMount is called. state:${JSON.stringify(this.state)}`);
            this.loadDataFromServer();
            let pollInterval = this.props.pollInterval;
            if (pollInterval) {
                setInterval(this.loadDataFromServer.bind(this), pollInterval);
            } else {
                setInterval(this.loadDataFromServer.bind(this), 5000);
            }
        }
        componentWillReceiveProps(nextProps: any, nextContext: any): void {
            console.log(this.state);
            console.log('componentWillReceiveProps, nextProps:', nextProps, ' nextContext', nextContext);
        }
        componentWillUpdate(nextProps: any, nextState: any, nextContext: any): void {
            //console.log('componentWillUpdate, nextProps:', nextProps, ' nextState:', nextState, ' nextContext:', nextContext);
        }
        componentDidUpdate(nextProps: any, nextState: any, nextContext: any): void {
            //console.log('componentDidUpdate, nextProps:', nextProps, ' nextState:', nextState, ' nextContext:', nextContext);
        }
        componentWillUnmount() {
            console.log('componentWillUnmount');
        }
        handleCommentSubmit = (comment) => {
            // TODO submit to the sever and refresh the list
            let comments = this.state.data;
            console.log(comment);
            /**
             * Optimistically set an id on the new comment.It will be replaced by an id generated
             * by the sever. In a production application you would likely not use Date.now() for
             * this and would have a more robust system in place.
             */
            comment.id = Date.now();
            let newComments = comments.concat([comment]);
            this.setState({ data: newComments });
            console.log(newComments)
            console.log(222)

            $.ajax({
                url: this.props.url,
                dataType: 'json',
                type: 'POST',
                data: comment,
                success: ((data) => {
                    this.setState(data);
                }).bind(this),
                error: ((xhr, status, err) => {
                    this.setState({ data: comments });
                    console.error(this.props.url, status, err.toString);
                }).bind(this)
            });
        }

        render() {
            let data: { id: number; author: string, text: string }[];
            if (this.state) {
                data = this.state.data;
            } else if (this.props) {
                data = this.props.data;
            }
            return (
                <div className='commentBox'>
                    <h1>Comments</h1>
                    <CommentList data={data} />
                    <CommentForm onCommentSubmit={this.handleCommentSubmit} />
                </div>
            );
        }

    }

}